<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Token Counter</title>
  <style>
  * {
    box-sizing: border-box;
  }

  body {
    font-family: Helvetica, Arial, sans-serif;
    line-height: 1.6;
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
  }

  textarea {
    width: 100%;
    min-height: 200px;
    margin: 10px 0;
    padding: 10px;
    font-size: 16px;
    font-family: monospace;
    border: 1px solid #ccc;
    border-radius: 4px;
  }

  button {
    background: #0066ff;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
  }

  button:disabled {
    background: #cccccc;
    cursor: not-allowed;
  }

  .output {
    background: #f5f5f5;
    padding: 20px;
    border-radius: 4px;
    margin-top: 20px;
    white-space: pre-wrap;
    font-family: monospace;
  }

  .error {
    color: #ff0000;
    margin: 10px 0;
  }

  .input-group {
    margin-bottom: 20px;
  }

  label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold;
  }

  .file-drop-area {
    border: 2px dashed #ccc;
    border-radius: 4px;
    padding: 20px;
    text-align: center;
    margin: 20px 0;
    background: #f8fafc;
    cursor: pointer;
  }

  .file-drop-area.drag-over {
    background: #e2e8f0;
    border-color: #0066ff;
  }

  .file-list {
    margin: 10px 0;
  }

  .file-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px;
    background: #f5f5f5;
    border-radius: 4px;
    margin: 4px 0;
  }

  .file-item button {
    background: #ff3333;
    padding: 4px 8px;
    font-size: 14px;
  }

  .file-item button:hover {
    background: #cc0000;
  }
  </style>
</head>
<body>
  <h1>Claude Token Counter</h1>
  
  <div class="input-group">
    <label for="system">System prompt:</label>
    <textarea id="system" style="min-height: 100px" placeholder="Enter system prompt (optional)"></textarea>
  </div>

  <div class="input-group">
    <label for="content">User message:</label>
    <textarea id="content" placeholder="Enter message content"></textarea>
  </div>

  <div class="file-drop-area" id="dropArea">
    <p>Drag and drop files here or click to select</p>
    <input type="file" id="fileInput" multiple style="display: none">
    <div class="file-list" id="fileList"></div>
  </div>

  <button id="count">Count Tokens</button>
  <div id="error" class="error"></div>
  <div id="output" class="output"></div>

<script type="module">
const API_URL = 'https://api.anthropic.com/v1/messages/count_tokens'
const MODEL = 'claude-sonnet-4-5'

let attachedFiles = []

function getApiKey() {
  let key = localStorage.getItem('ANTHROPIC_API_KEY')
  if (!key) {
    key = prompt('Please enter your Anthropic API key:')
    if (key) {
      localStorage.setItem('ANTHROPIC_API_KEY', key)
    }
  }
  return key
}

function handleFiles(files) {
  for (const file of files) {
    if (file.type.startsWith('image/') || file.type === 'application/pdf') {
      readAndStoreFile(file)
    } else {
      errorDiv.textContent = `Unsupported file type: ${file.type}`
    }
  }
}

function readAndStoreFile(file) {
  const reader = new FileReader()
  reader.onload = function(e) {
    const base64Data = e.target.result.split(',')[1]
    attachedFiles.push({
      name: file.name,
      type: file.type,
      data: base64Data
    })
    updateFileList()
  }
  reader.readAsDataURL(file)
}

function updateFileList() {
  const fileList = document.getElementById('fileList')
  fileList.innerHTML = attachedFiles.map((file, index) => `
    <div class="file-item">
      <span>${file.name} (${file.type})</span>
      <button onclick="removeFile(${index})">Remove</button>
    </div>
  `).join('')
}

window.removeFile = function(index) {
  attachedFiles.splice(index, 1)
  updateFileList()
}

async function countTokens(system, content) {
  const apiKey = getApiKey()
  if (!apiKey) {
    throw new Error('API key is required')
  }

  const messageContent = []
  
  // Add files first
  for (const file of attachedFiles) {
    messageContent.push({
      type: file.type.startsWith('image/') ? 'image' : 'document',
      source: {
        type: 'base64',
        media_type: file.type,
        data: file.data
      }
    })
  }

  // Add text content if present
  if (content.trim()) {
    messageContent.push({
      type: 'text',
      text: content
    })
  }

  const messages = [{
    role: 'user',
    content: messageContent
  }]

  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'x-api-key': apiKey,
      'content-type': 'application/json',
      'anthropic-version': '2023-06-01',
      'anthropic-beta': 'token-counting-2024-11-01,pdfs-2024-09-25',
      'anthropic-dangerous-direct-browser-access': 'true'
    },
    body: JSON.stringify({
      model: MODEL,
      system: system || undefined,
      messages
    })
  })

  if (!response.ok) {
    const error = await response.text()
    throw new Error(`API error: ${error}`)
  }

  return response.json()
}

const systemInput = document.getElementById('system')
const contentInput = document.getElementById('content')
const countButton = document.getElementById('count')
const errorDiv = document.getElementById('error')
const outputDiv = document.getElementById('output')
const dropArea = document.getElementById('dropArea')
const fileInput = document.getElementById('fileInput')

// File upload handling
dropArea.addEventListener('click', () => fileInput.click())
fileInput.addEventListener('change', (e) => handleFiles(e.target.files))

dropArea.addEventListener('dragover', (e) => {
  e.preventDefault()
  dropArea.classList.add('drag-over')
})

dropArea.addEventListener('dragleave', () => {
  dropArea.classList.remove('drag-over')
})

dropArea.addEventListener('drop', (e) => {
  e.preventDefault()
  dropArea.classList.remove('drag-over')
  handleFiles(e.dataTransfer.files)
})

countButton.addEventListener('click', async () => {
  errorDiv.textContent = ''
  outputDiv.textContent = 'Counting tokens...'
  countButton.disabled = true

  try {
    const result = await countTokens(
      systemInput.value.trim(),
      contentInput.value.trim()
    )
    outputDiv.textContent = JSON.stringify(result, null, 2)
  } catch (error) {
    errorDiv.textContent = error.message
    outputDiv.textContent = ''
  } finally {
    countButton.disabled = false
  }
})
</script>
</body>
</html>